package com.huidu.bitrade.controller.system;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.huidu.bitrade.constant.SysConstant;
import com.huidu.bitrade.dto.MemberWalletModifyDTO;
import com.huidu.bitrade.entity.Member;
import com.huidu.bitrade.entity.MemberWallet;
import com.huidu.bitrade.entity.MemberWalletOperLog;
import com.huidu.bitrade.pagination.PageResult;
import com.huidu.bitrade.query.WalletModifyMemberPageQuery;
import com.huidu.bitrade.result.page.PageCondition;
import com.huidu.bitrade.service.*;
import com.huidu.bitrade.util.GeneratorUtil;
import com.huidu.bitrade.util.MessageResult;
import com.huidu.bitrade.util.RedisUtil;
import com.huidu.bitrade.vendor.provider.SMSProvider;
import com.huidu.bitrade.vendor.provider.result.RestResult;
import com.huidu.bitrade.vo.MemberWalletModifyVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.lang.reflect.InvocationTargetException;
import java.sql.Wrapper;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;


@Api(tags = "修改用户余额")
@RequiredArgsConstructor
@RestController
@RequestMapping("walletModify")
public class MemberWalletModifyController {

    private final MemberWalletMpService memberWalletMpService;
    private final MemberWalletService memberWalletService;
    private final MemberService memberService;
    private final ExchangeOrderService exchangeOrderService;
    private final WithdrawRecordService withdrawRecordService;
    private final OrderService orderService;
    private final MemberWalletOperLogService MemberWalletOperLogService;
    private final SMSProvider smsProvider;
    private final RedisTemplate redisTemplate;
    private final List<String> phones = new ArrayList<>();

    @ApiOperation("查询用户余额")
    @GetMapping("memberPage")
    public MessageResult<PageResult<MemberWalletModifyVo>> memberPage(WalletModifyMemberPageQuery memberPageQuery){
        return MessageResult.success("查询成功",new PageResult<>(memberWalletMpService.pageList(PageCondition.page(memberPageQuery),memberPageQuery)));
    }

    @ApiOperation("修改用户余额")
    @PostMapping("modify")
    public MessageResult modify(@Valid MemberWalletModifyDTO modifyDTO, HttpServletRequest request) throws InvocationTargetException, IllegalAccessException {
        ValueOperations valueOperations = redisTemplate.opsForValue();
        String key = SysConstant.ADMIN_MODIFY_MEMBER_WALLET_PREFIX + modifyDTO.getPhone();
        // 缓存验证码
        Object cacheCode = valueOperations.get(key);
        Object codeCount = valueOperations.get(key+cacheCode);
        if(Objects.isNull(cacheCode)||Objects.isNull(codeCount)){
            return MessageResult.error("请先获取验证码");
        }
        if(!Objects.equals(modifyDTO.getOperCode(),cacheCode)){
            if((int)codeCount<1){
                valueOperations.getOperations().delete(key);
                valueOperations.getOperations().delete(key+cacheCode);
                return MessageResult.error("验证码已过期");
            }
            valueOperations.set(key+cacheCode, (int)codeCount-1, 5, TimeUnit.MINUTES);
            return MessageResult.error("验证码错误");
        }
        valueOperations.getOperations().delete(key);
        valueOperations.getOperations().delete(key+cacheCode);
        //判断用户钱包是否存在
        MemberWallet memberWallet = memberWalletService.findOne(modifyDTO.getWalletId());
        Assert.notNull(memberWallet, "钱包信息不存在，请核对");
        Member member = memberService.findOne(memberWallet.getMemberId());
        Assert.notNull(member, "用户不存在，请核对");
        modifyDTO.setIp(remoteIp(request));
        memberWalletMpService.modifyBalance(modifyDTO,memberWallet);
        return MessageResult.success();
    }

    @ApiOperation("判断用户指定币种是否有进行中的交易")
    @GetMapping("isHaveDeal")
    public MessageResult isHaveDeal(@RequestParam("memberId") Long memberId,@RequestParam("unit") String unit){
        //判断是否存在币币交易挂单
        long exchangeOrderCount = exchangeOrderService.findUserTradingOrderCount(memberId,unit);
        if(exchangeOrderCount>0){
            return MessageResult.error("该用户的当前币种存在币币交易挂单操作，建议您仔细查看后再进行修改！");
        }
        //判断是否提币
        long withCount = withdrawRecordService.memberAuditingCount(memberId,unit);
        if(withCount>0){
            return MessageResult.error("该用户的当前币种存在未审核的提币申请，建议您仔细查看后再进行修改！");
        }
        //判断是否otc交易中
        long otcCount = orderService.findAllProcessingUnitOrder(memberId,unit);
        if(otcCount>0){
            return MessageResult.error("该用户的当前币种存在otc交易中的订单，建议您仔细查看后再进行修改！");
        }
        return MessageResult.success();
    }

    @Value("#{'${modify.member.wallet.phone:}'.split(',')}")
    public void setMonitorList(List<String> codeList) {
        this.phones.addAll(codeList);
    }

    public String remoteIp(HttpServletRequest request) {
        if (StringUtils.isNotBlank(request.getHeader("X-Real-IP"))) {
            return request.getHeader("X-Real-IP");
        } else if (StringUtils.isNotBlank(request.getHeader("X-Forwarded-For"))) {
            return request.getHeader("X-Forwarded-For");
        } else if (StringUtils.isNotBlank(request.getHeader("Proxy-Client-IP"))) {
            return request.getHeader("Proxy-Client-IP");
        }
        return request.getRemoteAddr();
    }

    @ApiOperation("查询用户余额操作记录")
    @GetMapping("operLogs/{walletId}")
    public MessageResult<MemberWalletOperLog> operLogs(@PathVariable Long walletId){
        return MessageResult.success("查询成功",MemberWalletOperLogService.list(Wrappers.<MemberWalletOperLog>lambdaQuery().eq(MemberWalletOperLog::getWalletId,walletId)));
    }


    @ApiOperation("获取验证码")
    @GetMapping("getCode/{phone}")
    public MessageResult getCode(@PathVariable String phone) throws Exception {
        //判断授权码是否可用
        if(!phones.contains(phone)){
            return MessageResult.error("此手机号无权限");
        }
        //发送验证码
        String randomCode = String.valueOf(GeneratorUtil.getRandomNumber(100000, 999999));
        RestResult result = smsProvider.sendMessageByTempId(phone, Collections.singletonList(randomCode),10);
        if (result.getCode() == 0) {
            ValueOperations valueOperations = redisTemplate.opsForValue();
            String key = SysConstant.ADMIN_MODIFY_MEMBER_WALLET_PREFIX + phone;
            valueOperations.getOperations().delete(key);
            // 缓存验证码
            valueOperations.set(key, randomCode, 5, TimeUnit.MINUTES);
            String codekey = SysConstant.ADMIN_MODIFY_MEMBER_WALLET_PREFIX + phone+randomCode;
            valueOperations.set(codekey, 2, 5, TimeUnit.MINUTES);
            return MessageResult.success("短信发送成功");
        } else {
            return MessageResult.error("短信发送失败");
        }
    }


}
